package com.dotflat.utils;

import com.alibaba.fastjson.JSON;

import com.starinside.wp.foundation.exception.BusinessException;
import com.starinside.wp.utils.HttpClientUtil;
import com.starinside.wp.utils.JsonUtil;
import com.starinside.wp.utils.RemoteCallUtil;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;

import static org.apache.http.protocol.HTTP.USER_AGENT;

public class RemoteCallUtilAddon extends RemoteCallUtil {


    public static final String REMOTE_CALL_ERROR = "999998";
    private static int connectTimeout = 3000;  // 链接超时
    private static int connectionRequestTimeout = 6000;  // 读取超时

    static CloseableHttpClient httpClient = null;

    static {
        httpClient = HttpClients.createDefault();
    }

    private static String sendHttpMethod(HttpRequestBase method) throws IOException {
        //config
        RequestConfig config = RequestConfig.custom()
                .setConnectTimeout(connectTimeout)
                .setConnectionRequestTimeout(connectionRequestTimeout)
                .build();
        method.setConfig(config);

        //UA
        method.setHeader(USER_AGENT, "Apache-HttpClient/4.1.1 (java 1.5)");

        String soapResponseData = null;
        // Execute the method.
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(method);
            //status code
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != HttpStatus.SC_OK) {
                System.err.println("Method failed: " + response.getStatusLine());
            }
            //获取返回
            HttpEntity entity = response.getEntity();
            soapResponseData = EntityUtils.toString(entity);
        } catch (IOException e) {
            System.err.println("Fatal transport error: " + e.getMessage());
            throw e;
        } catch (Exception e) {
            e.getStackTrace();
        } finally {
            try {
                response.close();
            } catch (Exception e) {
                e.getStackTrace();
            }
            try {
                method.abort();
            } catch (Exception e) {
                e.getStackTrace();
            }

            // Release the connection.
            method.releaseConnection();
        }

        return soapResponseData;
    }

    public static String sendGet(String url, Map<String, String> params, Map headers) throws IOException, URISyntaxException {

        URIBuilder uriBuilder = new URIBuilder(url);
        if (params != null && params.size() > 0){
            params.entrySet().stream().forEach(o ->{
                uriBuilder.addParameter(o.getKey(), o.getValue());
            });
        }

        URI uri = uriBuilder.build();

        HttpGet getMethod = new HttpGet(uri.toString());

        getMethod.setHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");

        if (Objects.nonNull(headers)) {
            Iterator iter = headers.keySet().iterator();

            while(iter.hasNext()) {
                String name = (String)iter.next();
                String value = String.valueOf(headers.get(name));
                getMethod.setHeader(name, value);
            }
        }

        return sendHttpMethod(getMethod);
    }

    /**
     * 返回list的方法
     * @param url 请求地址
     * @param params 请求参数
     * @param ticket 票据
     * @param clazz 需要返回的类型
     * @param errorMsg 异常后需要抛出的错误信息
     * @param <T>
     * @return
     */
    public static <T> List<T> getList(String url, Map<String, String> params, String ticket, Class<T> clazz, String errorMsg) {
        try {

            Map headers = new HashMap();
            signRequest(headers, url, ticket);

            String responseJson = sendGet(url, params, headers);

            List<T> response = JsonUtil.readListFormJson(responseJson, clazz);

            return response;
        } catch (BusinessException e){
            e.printStackTrace();
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(REMOTE_CALL_ERROR, errorMsg);
        }
    }

    /**
     * 返回list的方法
     * @param url 请求地址
     * @param params 请求参数
     * @param ticket 票据
     * @param clazz 需要返回的类型
     * @param errorMsg 异常后需要抛出的错误信息
     * @param <T>
     * @return
     */
    public static <T> List<T> postList(String url, Map<String, String> params, String ticket, Class<T> clazz, String errorMsg) {
        try {

            Map headers = new HashMap();
            signRequest(headers, url, ticket);

            String responseJson = HttpClientUtil.sendPost(url, params, headers);

            List<T> response = JsonUtil.readListFormJson(responseJson, clazz);

            return response;
        } catch (BusinessException e){
            e.printStackTrace();
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(REMOTE_CALL_ERROR, errorMsg);
        }
    }


    /**
     * 返回单个实体方法
     * @param url 请求地址
     * @param params 请求参数
     * @param ticket 票据
     * @param errorMsg 异常后需要抛出的错误信息
     * @return
     */
    public static Map getMap(String url, Map params, String ticket, String errorMsg) {
        try {
            Map headers = new HashMap();
            signRequest(headers, url, ticket);

            String responseJson = sendGet(url, params, headers);

            Map result = JsonUtil.readToMap(responseJson);

            return result;
        } catch (BusinessException e){
            e.printStackTrace();
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(REMOTE_CALL_ERROR, errorMsg);
        }
    }

    /**
     * 返回单个实体方法
     * @param url 请求地址
     * @param params 请求参数
     * @param ticket 票据
     * @param errorMsg 异常后需要抛出的错误信息
     * @return
     */
    public static Map postMap(String url, Map params, String ticket, String errorMsg) {
        try {
            Map headers = new HashMap();
            signRequest(headers, url, ticket);

            String responseJson = HttpClientUtil.sendPost(url, params, headers);

            Map result = JsonUtil.readToMap(responseJson);

            return result;
        } catch (BusinessException e){
            e.printStackTrace();
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(REMOTE_CALL_ERROR, errorMsg);
        }
    }

    /**
     * 返回单个实体方法
     * @param url 请求地址
     * @param params 请求参数
     * @param ticket 票据
     * @param errorMsg 异常后需要抛出的错误信息
     * @return
     */
    public static <T> T getObject(String url, Map params, String ticket, Class<T> clazz, String errorMsg) {
        try {
            Map headers = new HashMap();
            signRequest(headers, url, ticket);

            String responseJson = sendGet(url, params, headers);

            T result = JSON.parseObject(responseJson, clazz);
            return result;

        } catch (BusinessException e){
            e.printStackTrace();
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(REMOTE_CALL_ERROR, errorMsg);
        }
    }
}